# -*- coding: binary -*-
module Msf

require 'msf/core/exploit/tcp'

###
#
# This module exposes methods that may be useful to exploits that deal with
# servers that speak the SMTP protocol.
#
###
module Exploit::Remote::Smtp

  include Exploit::Remote::Tcp

  #
  # Creates an instance of an SMTP exploit module.
  #
  def initialize(info = {})
    super

    # Register the options that all SMTP exploits may make use of.
    register_options(
      [
        Opt::RHOST,
        Opt::RPORT(25),
        OptString.new('MAILFROM', [ true, 'FROM address of the e-mail', 'sender@example.com']),
        OptString.new('MAILTO', [ true, 'TO address of the e-mail', 'target@example.com']),
      ], Msf::Exploit::Remote::Smtp)
    register_autofilter_ports([ 25, 465, 587, 2525, 25025, 25000])
    register_autofilter_services(%W{ smtp smtps})
  end

  #
  # This method establishes a SMTP connection to host and port specified by
  # the RHOST and RPORT options, respectively.  After connecting, the banner
  # message is read in and stored in the 'banner' attribute.
  #
  def connect(global = true)
    fd = super

    # Wait for a banner to arrive...
    self.banner = fd.get_once(-1, 30)
    # Return the file descriptor to the caller
    fd
  end

  #
  # Connect to the remote SMTP server, and begin a DATA transfer
  #
  def connect_login(global = true)
    smtpsock = connect(global)

    raw_send_recv("EHLO X\r\n")
    raw_send_recv("MAIL FROM: #{datastore['MAILFROM']}\r\n")
    raw_send_recv("RCPT TO: #{datastore['MAILTO']}\r\n")
    raw_send_recv("DATA\r\n")

    return true
  end

  #
  # This method transmits an IMAP command and waits for a response.  If one is
  # received, it is returned to the caller.
  #
  def raw_send_recv(cmd, nsock = self.sock)
    nsock.put(cmd)
    nsock.get_once
  end

protected

  #
  # This attribute holds the banner that was read in after a successful call
  # to connect or connect_login.
  #
  attr_accessor :banner

end

end

